package com.kexio.file.mapper;

import java.time.LocalDateTime;
import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.kexio.file.entity.StorageObject;

/**
 * 存储对象数据访问层
 * 
 * 基于MyBatis Plus的存储对象数据访问接口，提供：
 * - 基础CRUD操作（继承自BaseMapper）
 * - 存储对象去重查询
 * - 引用计数管理
 * - 存储统计和分析
 * - 多租户数据隔离
 * 
 * @author Kexio Team
 * @since 1.0.0
 */
@Mapper
public interface StorageObjectMapper extends BaseMapper<StorageObject> {
    
    // ==================== 去重查询 ====================
    
    /**
     * 根据内容哈希查询存储对象（用于去重）
     * 
     * @param contentHash 内容哈希值
     * @param tenantId 租户ID（可选）
     * @return 存储对象
     */
    StorageObject selectByContentHash(@Param("contentHash") String contentHash, 
                                      @Param("tenantId") String tenantId);
    
    /**
     * 根据存储路径查询存储对象
     * 
     * @param storageType 存储类型
     * @param bucketName 存储桶名称
     * @param storagePath 存储路径
     * @param tenantId 租户ID（可选）
     * @return 存储对象
     */
    StorageObject selectByStoragePath(@Param("storageType") String storageType,
                                      @Param("bucketName") String bucketName,
                                      @Param("storagePath") String storagePath,
                                      @Param("tenantId") String tenantId);
    
    // ==================== 引用计数管理 ====================
    
    /**
     * 增加引用计数
     * 
     * @param storageObjectId 存储对象ID
     * @param increment 增加数量（默认1）
     * @return 更新行数
     */
    int incrementReferenceCount(@Param("storageObjectId") String storageObjectId, 
                                @Param("increment") Integer increment);
    
    /**
     * 减少引用计数
     * 
     * @param storageObjectId 存储对象ID
     * @param decrement 减少数量（默认1）
     * @return 更新行数
     */
    int decrementReferenceCount(@Param("storageObjectId") String storageObjectId, 
                                @Param("decrement") Integer decrement);
    
    /**
     * 查询可清理的存储对象（引用计数为0）
     * 
     * @param tenantId 租户ID（可选）
     * @param limit 限制数量
     * @return 存储对象列表
     */
    List<StorageObject> selectCleanableObjects(@Param("tenantId") String tenantId,
                                               @Param("limit") Integer limit);
    
    // ==================== 存储统计 ====================
    
    /**
     * 按存储类型统计存储对象数量
     * 
     * @param storageType 存储类型
     * @param tenantId 租户ID（可选）
     * @return 存储对象数量
     */
    Long countByStorageType(@Param("storageType") String storageType, 
                            @Param("tenantId") String tenantId);
    
    /**
     * 按存储类型统计存储大小
     * 
     * @param storageType 存储类型
     * @param tenantId 租户ID（可选）
     * @return 存储总大小（字节）
     */
    Long sumSizeByStorageType(@Param("storageType") String storageType, 
                              @Param("tenantId") String tenantId);
    
    /**
     * 统计重复文件节省的空间
     * 
     * @param tenantId 租户ID（可选）
     * @return 节省的空间（字节）
     */
    Long calculateSpaceSaved(@Param("tenantId") String tenantId);
    
    /**
     * 统计存储配置使用情况
     * 
     * @param storageConfig 存储配置名称
     * @param tenantId 租户ID（可选）
     * @return 使用统计
     */
    Long countByStorageConfig(@Param("storageConfig") String storageConfig, 
                              @Param("tenantId") String tenantId);
    
    // ==================== 存储维护 ====================
    
    /**
     * 查询需要验证的存储对象
     * 
     * @param lastVerifyBefore 最后验证时间之前
     * @param tenantId 租户ID（可选）
     * @param limit 限制数量
     * @return 存储对象列表
     */
    List<StorageObject> selectObjectsNeedVerify(@Param("lastVerifyBefore") LocalDateTime lastVerifyBefore, 
                                                @Param("tenantId") String tenantId,
                                                @Param("limit") Integer limit);
    
    /**
     * 更新验证状态
     * 
     * @param storageObjectId 存储对象ID
     * @param verifyStatus 验证状态
     * @param verifyTime 验证时间
     * @return 更新行数
     */
    int updateVerifyStatus(@Param("storageObjectId") String storageObjectId, 
                           @Param("verifyStatus") Integer verifyStatus,
                           @Param("verifyTime") LocalDateTime verifyTime);
    
    /**
     * 批量更新存储对象状态
     * 
     * @param storageObjectIds 存储对象ID列表
     * @param status 新状态
     * @param updateBy 更新者
     * @return 更新行数
     */
    int batchUpdateStatus(@Param("storageObjectIds") List<String> storageObjectIds, 
                          @Param("status") Integer status,
                          @Param("updateBy") String updateBy);
    
    // ==================== 复杂查询 ====================
    
    /**
     * 搜索存储对象（支持多条件组合）
     * 
     * @param storageType 存储类型（可选）
     * @param storageConfig 存储配置（可选）
     * @param bucketName 存储桶名称（可选）
     * @param minSize 最小文件大小（可选）
     * @param maxSize 最大文件大小（可选）
     * @param status 状态（可选）
     * @param verifyStatus 验证状态（可选）
     * @param isEncrypted 是否加密（可选）
     * @param startTime 开始时间（可选）
     * @param endTime 结束时间（可选）
     * @param tenantId 租户ID（可选）
     * @param page 分页参数
     * @return 分页结果
     */
    IPage<StorageObject> searchStorageObjects(@Param("storageType") String storageType,
                                              @Param("storageConfig") String storageConfig,
                                              @Param("bucketName") String bucketName,
                                              @Param("minSize") Long minSize,
                                              @Param("maxSize") Long maxSize,
                                              @Param("status") Integer status,
                                              @Param("verifyStatus") Integer verifyStatus,
                                              @Param("isEncrypted") Boolean isEncrypted,
                                              @Param("startTime") LocalDateTime startTime,
                                              @Param("endTime") LocalDateTime endTime,
                                              @Param("tenantId") String tenantId,
                                              IPage<StorageObject> page);
}
